﻿/**
* pcm2wav.c
* add wav head for pcm data
* head length =44
*/

#include <stdio.h>  
#include <string.h>  
#include <stdlib.h>
#include "MiAudio.h"


#pragma warning (disable :4996)

#define  uint32_t       unsigned int  
#define  uint16_t       unsigned short   


typedef struct _riff_t
{
	char riff[4];	/* "RIFF" (ASCII characters) */
	uint32_t len;	/* Length of package (binary, little endian) */
	char wave[4];	/* "WAVE" (ASCII characters) */
} riff_t;

/* The FORMAT chunk */

typedef struct _format_t {
	char  fmt[4];		/* "fmt_" (ASCII characters) */
	uint32_t   len;	/* length of FORMAT chunk (always 0x10) */
	uint16_t  type;		/* codec type*/
	uint16_t channel;	/* Channel numbers (0x01 = mono, 0x02 = stereo) */
	uint32_t   rate;	/* Sample rate (binary, in Hz) */
	uint32_t   bps;	/* Average Bytes Per Second */
	uint16_t blockalign;	/*number of bytes per sample */
	uint16_t bitpspl;	/* bits per sample */
} format_t;

typedef struct _data_t {
	char data[4];   /* "data" (ASCII characters) */
	uint32_t len;  /* length of data */
}data_t;

typedef struct _wav_head
{
	riff_t riff;
	format_t format;
	data_t   data;
}wav_head;

void PcmToWav(char*src_file, char* dst_file, int channels, int bits, int sample_rate)
{
	/*char src_file[128] = { 0 };
	char dst_file[128] = { 0 };*/
	/*char *src_file = "48000_2_.pcm";
	char *dst_file = "aaa.wav";*/
	// 	int channels = 1;//通道1
	// 	int bits = 16;
	//int sample_rate = 48000;
	//以下是为了建立.wav头而准备的变量    
	wav_head header;
	FILE   *fp, *fpCpy;
	printf("parameter analyse succeess\n");
	if ((fp = fopen(src_file, "rb")) == NULL) //读取文件    
	{
		printf("open pcm file  error\n");
		return;
	}
	if ((fpCpy = fopen(dst_file, "wb")) == NULL) //为转换建立一个新文件    
	{
		printf("create wav file error\n");
		return;
	}
	//以下是创建wav头的HEADER;但.dwsize未定，因为不知道Data的长度。    
	memcpy(header.riff.riff, "RIFF", 4);
	memcpy(header.riff.wave, "WAVE", 4);
	//以上是创建wav头的HEADER;    
	if (ferror(fpCpy))
	{
		printf("error\n");
	}
	memcpy(&header.format.fmt, "fmt ", 4);
	header.format.len = 0x10;
	header.format.type = 0x1;
	header.format.channel = channels;
	header.format.rate = sample_rate;
	header.format.bps = sample_rate * bits / 8 * channels;
	header.format.blockalign = bits / 8 * channels;
	header.format.bitpspl = bits;
	memcpy(&header.data.data, "data", 4);
	fseek(fp, 0, SEEK_END);
	long count = ftell(fp);
	fseek(fp, 0, SEEK_SET);
	printf("length:%ud", count);
	header.data.len = (uint32_t)count;
	header.riff.len = header.data.len + 36;
	int size = sizeof(header);
	//fwrite(&header, 1, sizeof(header), fpCpy);
	fwrite(&header, sizeof(header), 1, fpCpy);
	char *buffer = (char *)malloc((count)* sizeof(char));
	fread(buffer, 1, count, fp);
	//fwrite(buffer, 1, count, fpCpy);
	fwrite(buffer, 1, count, fpCpy);
	free(buffer);
	fclose(fp); //关闭文件    
	fclose(fpCpy);   //关闭文件    

}





























//				WavToPcm
/**************************************/
//后面的结构可能不是直接为“data”
/******不是直接去掉44个字节*************/
/**************************************/

/***********/
/*
size_t fread(
	void *buffer,数据的存储位置。
	size_t size,项目大小 (以字节为单位)。
	size_t count,要读取项目的最大数量
	FILE *stream指向 FILE 结构的指针。
	);
	/*****************/
void WavToPcm(char* src_file)
{
	//char *src_file = "aa.wav";
	//	char *src_file = "aa.wav";
	uint32_t pcm_data_size = 0;
	int pcm_channel = 0;
	int pcm_samplerate = 0;
	//以下是为了建立.wav头而准备的变量    
	wav_head header;
	FILE   *fp = NULL, *fpCpy = NULL;
	int flen;
	if ((fp = fopen(src_file, "rb")) == NULL) //读取文件    
	{
		printf("open pcm file  error\n");
		return;
	}
	//简单粗暴方式  直接去掉44个字节
	//if ((flen=fread(&header,1,44,fp))!=44) 
	//{
	//	goto error;
	//}

	if ((flen = fread(&header.riff.riff, 1, 4, fp)) != 4)
		goto error;

	if (memcmp(&header.riff.riff, "RIFF", 4))
		goto error;

	if ((flen = fread(&header.riff.len, 1, 4, fp)) != 4)
		goto error;

	//pcm_data_size = header.riff.len - 36;

	if ((flen = fread(&header.riff.wave, 1, 4, fp)) != 4)
		goto error;

	if (memcmp(&header.riff.wave, "WAVE", 4))
		goto error;

	if ((flen = fread(&header.format.fmt, 1, 4, fp)) != 4)
		goto error;

	if (memcmp(&header.format.fmt, "fmt ", 4))
		goto error;

	if ((flen = fread(&header.format.len, 1, 4, fp)) != 4)
	{
		goto error;
	}
	if (header.format.len != 0x10)
	{
		printf("header.format.len!=0x10 :value:%d\n", header.format.len);
	}
	if ((flen = fread(&header.format.type, 1, 2, fp)) != 2)
	{
		goto error;
	}
	if (header.format.type != 0x1)
	{
		printf("header.format.type != 0x1 :value:%d\n", header.format.type);
	}
	if ((flen = fread(&header.format.channel, 1, 2, fp)) != 2)
	{
		goto error;
	}
	pcm_channel = header.format.channel;//通道数的数据，，，可能吧😂

	if ((flen = fread(&header.format.rate, 1, 4, fp)) != 4)
	{
		goto error;
	}
	pcm_samplerate = header.format.rate;

	if ((flen = fread(&header.format.bps, 1, 4, fp)) != 4)
	{
		goto error;
	}

	if ((flen = fread(&header.format.blockalign, 1, 2, fp)) != 2)
	{
		goto error;
	}

	if ((flen = fread(&header.format.bitpspl, 1, 2, fp)) != 2)
	{
		goto error;
	}

	int p = 0;
	//后面的结构可能不是直接为“data”
	do {
		if ((flen = fread(&header.data.data, 1, 4, fp)) != 4)
		{
			goto error;
		}
		if (memcmp(&header.data.data, "data", 4) == 0)
		{
			printf("find data chunk.");
			if ((flen = fread(&header.data.len, 1, 4, fp)) != 4)
			{
				goto error;
			}
			pcm_data_size = header.data.len;
			break;
		}
		else
			p += 4;

	} while (!feof(fp));


	printf("解析成功，二个PCM数据长度分别为:%d, %d\n", pcm_data_size, header.riff.len - 36);

	int otherdataSize = header.riff.len - 36 - pcm_data_size;
	if (otherdataSize > 0)
	{
		printf("多余的数据部分大小：%d , %d", p, otherdataSize);
		char *otherdata = (char *)malloc(otherdataSize + 1);
		memset(otherdata, 0, otherdataSize + 1);
		fseek(fp, -otherdataSize - 8, SEEK_CUR);
		fread(otherdata, 1, otherdataSize, fp);
		*(otherdata + otherdataSize) = '\0';
		fseek(fp, 8, SEEK_CUR);
		printf("other data:%s", otherdata);
	}
	fseek(fp, otherdataSize + 44, SEEK_SET);

	//fseek(fp, 0, SEEK_CUR);

	unsigned char *buffer = (unsigned char*)malloc((pcm_data_size)* sizeof(char));

	memset(buffer, 0, pcm_data_size);


	int count1 = fread(buffer, 1, pcm_data_size, fp);


	char output[1024] = { 0 };
	//sprintf(output, "%d_%d_.pcm", pcm_samplerate, pcm_channel);
	sprintf(output, "%d_%d_.pcm", pcm_samplerate, pcm_channel);

	if ((fpCpy = fopen(output, "wb+")))
	{
		//fwrite(buffer, 1, sizeof(buffer), fpCpy);  写了段常犯错的代码
		fwrite(buffer, 1, pcm_data_size, fpCpy);
	}
	else
		goto error;

	free(buffer);
	fclose(fp); //关闭文件    
	fclose(fpCpy);   //关闭文件    

	return;

error:
	if (fp)
	{
		fclose(fp);
	}
	if (fpCpy)
	{
		fclose(fpCpy);
	}
	return;
}
